import type { CSSProperties, Component } from 'vue'
import type { ValidateFieldsError } from 'async-validator'
import type { RuleItem } from './rule'

interface Callback {
  (isValid?: boolean, invalidFields?: ValidateFieldsError): void
}

export interface FormOptions {
  // 表单项显示的元素
  type: 'cascader' | 'checkbox' | 'checkbox-group' | 'checkbox-button' | 'color-picker' | 'date-picker' | 'input' | 'input-number' | 'input-password' | 'radio' | 'radio-group' | 'radio-button' | 'rate' |
    'select' | 'select-option' | 'slider' | 'switch' | 'time-picker' | 'data-picker' | 'time-select' |
    'transfer' | 'upload' | 'editor' | 'textarea' | 'table'
  // 表单项的值
  value?: any
  // 表单项label
  label?: string
  // 表单项的必填标识
  required?: string
  // 表单项的字段标识
  prop?: string
  id?: string
  // 表单项的验证规则
  rules?: RuleItem[]
  // 表单项的占位符
  placeholder?: string
  // 组件大小
  size?: string
  tooltip?: string
  disabled?: boolean
  // 表单元素特有的属性
  attrs?: {
    'allowClear'?: boolean
    'disabled'?: boolean
    'show-search'?: boolean
    'filter-option'?: (input: string, option: any) => any
    'mode'?: 'multiple' | 'tags' | 'combobox'
    'format'?: string // 选中显示的format
    'valueFormat'?: string // 提交的值format
    'style'?: CSSProperties
    'slot'?: string
    'icon'?: Component
    'styleIcon'?: CSSProperties
    'min'?: number
    'max'?: number
  }
  children?: FormOptions[]
  // 处理上传组件的属性和方法
  uploadAttrs?: {
    action?: string
    headers?: object
    method?: 'post' | 'put' | 'patch'
    multiple?: boolean
    maxCount?: number
    data?: any
    name?: string
    withCredentials?: boolean
    showFileList?: boolean
    drag?: boolean
    accept?: string
    thumbnailMode?: boolean
    fileList?: any[]
    listType?: 'text' | 'picture' | 'picture-card'
    autoUpload?: boolean
    disabled?: boolean
  }
}

export interface ValidateFieldCallback {
  (message?: string, invalidFields?: ValidateFieldsError): void
}

export interface FormInstance {
  registerLabelWidth: (width: number, oldWidth: number) => void
  deregisterLabelWidth: (width: number) => void
  autoLabelWidth: string | undefined
  emit: (evt: string, ...args: any[]) => void
  labelSuffix: string
  inline?: boolean
  model?: Record<string, unknown>
  size?: string
  showMessage?: boolean
  labelPosition?: string
  labelWidth?: string
  rules?: Record<string, unknown>
  statusIcon?: boolean
  hideRequiredAsterisk?: boolean
  disabled?: boolean
  validate: (callback?: Callback) => Promise<boolean>
  resetFields: () => void
  clearValidate: (props?: string | string[]) => void
  validateField: (props: string | string[], cb: ValidateFieldCallback) => void
}
